﻿
/*******************************************************************************
 **  Name:                                        **
 **  Description:                                                             **
 **                                                                           **
 **  CDDL: Open Source Initiative (OSI) Approved License                            **
 **                                                                           **
 **  Copyright (c) 2009-2010 Barry "Gian" James  <bjames@munixos.net>         **
 **  All rights reserved.                                                     **
 **                                                                           **
 **  The contents of this file are subject to the terms of the CDDL:          **
 **  Common Development and Distribution License (the "License").             **
 **  You may not use this file except in compliance with the License.         **
 **                                                                           **
 **  You can obtain a copy of the license at $PROJECT_ROOT/LICENSE            **
 **  or http://www.opensolaris.org/os/licensing.  This code is Open Source    **
 **  and you are free to use it within the confines of the license, even      **
 **  for your own closed-source commercial projects, as long as you follow    **
 **  the terms set forth in the CDDL.                                         **
 **                                                                           **
 **  When distributing Covered Code, include this CDDL HEADER in each         **
 **  file and include the License file at $PROJECT_ROOT/LICENSE.              **
 **  If applicable, add the following below this CDDL HEADER, with the        **
 **  fields enclosed by brackets "[]" replaced with your own identifying      **
 **  information: Portions Copyright [yyyy] [name of copyright owner]         **
 **                                                                           **
 ******************************************************************************/
// Created on November 1, 2010, 7:25 AM
// Modified $Date$ by $Author$
// $Id$
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Windows.Forms;

namespace sat1baf1
{
    public partial class WeaponInventoryForm : Form
    {
        MainForm mf;
        public WeaponInventoryForm(MainForm f)
        {
            InitializeComponent();
            mf = f;
            InitializeData();
            comboType.SelectedIndex = 1;
            labelNumMags.Text = "";
            labelRoundsType.Text = "";
        }

        private void InitializeData()
        {
#if DEBUG
            XmlLog.Instance.Add("InitializeData(): Starting");
            
#endif      // Load up the tree
            XElement weapondb = WeaponDB.Instance.Arsenal;

            IEnumerable<XElement> weapons =
                from el in weapondb.Elements("WEAPON")
                select el;
            foreach (XElement wpn in weapons)
            {
                // Get the name and node name 
                string name = (string)wpn.Element("NAME");
                string node = (string)wpn.Element("TYPE").Attribute("node");

                //MessageBox.Show("Adding " + name);
                TreeNode[] tn = treeWpns.Nodes[0].Nodes.Find(node, true);
                TreeNode nod = new TreeNode();
                //MessageBox.Show("AddItemToTree->Node." + 
                nod.Name = MakeID(name);
                nod.Text = name;
                tn[0].Nodes.Add(nod);
            }

#if DEBUG
            XmlLog.Instance.Add("InitializeData(): Ending");
            XmlLog.Instance.Add("Loaded " + weapondb.Elements("WEAPON").Count() + " weapons from arsenal.");
            
#endif            
        }
        private void btnWpnSize_Click(object sender, EventArgs e)
        {
            WeaponSizeForm form = new WeaponSizeForm(mf);
            form.Show();
        }

        private void btnWpnQual_Click(object sender, EventArgs e)
        {            
            // test
            //XDocument xdoc = XDocument.Load(@"Data Files\Weapons.xml");
            //var query = from names in xdoc.Descendants("NAME")
            //            where names.Value == "Colt M1911A1"
            //            select (string)names;

            //MessageBox.Show(String.Format("{0} found", query.Count()));
            //foreach (var item in query)
            //    rtTitle.Text = item.ToString();

            WeaponQualityForm form = new WeaponQualityForm(mf);
            form.Show();
        }

        private void btnNewImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
//            dlg.InitialDirectory = "c:\\";
            dlg.Filter = "bmp files (*.bmp)|*.bmp|jpg files (*.jpg)|*.jpg|All files (*.*)|*.*";
            dlg.FilterIndex = 3;
            dlg.RestoreDirectory = true;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                // Add image
            }

        }

        private void btnAddWpn_Click(object sender, EventArgs e)
        {
            // Clear all data
            rtTitle.Text = ""; textAmmo.Text = ""; textComplexityDC.Text = ""; textDamage.Text = ""; textErrorRange.Text = "";
            textRange.Text = ""; numAddOns.Value = 0; numGearCaliber.Value = 0; numRecoil.Value = 0; textCaliber.Text = "";
            textComplexityMod.Text = ""; textRangeMax.Text = ""; textStreetVal.Text = ""; textThreatRange.Text = "";
            textWeight.Text = ""; textWpnQual.Text = ""; textWpnSize.Text = ""; textYear.Text = "";
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            // Add to tree and Weapons.xml
            if (ValidateFields() == true)
            {
                MessageBox.Show(String.Format("UpdateButton: Request to add {0} as a {1}", rtTitle.Text, (string)comboType.SelectedItem));

                // Add to tree
                if (AddItemToTree((string)comboType.SelectedItem, rtTitle.Text) == false)
                {
                    MessageBox.Show("Cannot add " + rtTitle.Text + " to the tree.");
                    return;
                }

                // Add to file
                string [] str = textWpnSize.Text.Split('/');
                // WAS XElement
                XElement newWpn = new XElement("WEAPON",
                    new XElement("NAME", rtTitle.Text, new XAttribute("id", MakeID(rtTitle.Text))),
                    new XElement("CALIBER", textCaliber.Text),
                    new XElement("TYPE", comboType.SelectedItem, 
                        new XAttribute("family",GetClassByType()), 
                        new XAttribute("node",GetTreeNodeName((string)comboType.SelectedItem))),
                    new XElement("PICK", numGearCaliber.Value.ToString()),
                    new XElement("ADDONS", numAddOns.Value.ToString()),
                    new XElement("DMG", textDamage.Text),
                    new XElement("ERROR", textErrorRange.Text),
                    new XElement("THREAT", textThreatRange.Text),
                    new XElement("AMMO", textAmmo.Text),
                    new XElement("RECOIL", numRecoil.Value.ToString()),
                    new XElement("RANGE", textRange.Text),
                    new XElement("SIZE", str[0]),
                    new XElement("HANDS", str[1]),
                    new XElement("QUALITY", textWpnQual.Text),
                    new XElement("WEIGHT", textWeight.Text),
                    new XElement("COMPLEXITY", new XElement("DC", textComplexityDC.Text), new XElement("MOD", textComplexityMod.Text)),
                    new XElement("STREET", textStreetVal.Text),
                    new XElement("YEAR", textYear.Text),
                    new XElement("IMAGE", picWeapon.ImageLocation));

                WeaponDB.Instance.Add(newWpn);

            }
        }

        /// <summary>
        /// Reads the comboWpnType and returns the class of weapon
        /// eg Service Pistol -> Handgun
        /// eg Colt M4 -> AssaultRifle
        /// </summary>
        /// <returns></returns>
        private string GetClassByType()
        {
            if ((string)comboType.SelectedItem == "Service Pistol")
                return "handgun";
            if ((string)comboType.SelectedItem == "Backup Pistol")
                return "handgun";
            if ((string)comboType.SelectedItem == "Holdout Pistol")
                return "handgun";
            if ((string)comboType.SelectedItem == "Service Revolver")
                return "handgun";
            if ((string)comboType.SelectedItem == "Hunting Revolver")
                return "handgun";
            if ((string)comboType.SelectedItem == "Backup Revolver")
                return "handgun";
            if ((string)comboType.SelectedItem == "Blunt Melee")
                return "blunt";
            if ((string)comboType.SelectedItem == "Exotic Blunt")
                return "exotic_blunt";
            if ((string)comboType.SelectedItem == "Edged Melee")
                return "edged";
            if ((string)comboType.SelectedItem == "Exotic Edged")
                return "exotic_edged";
            if ((string)comboType.SelectedItem == "Hurled")
                return "hurled";
            if ((string)comboType.SelectedItem == "Exotic Hurled")
                return "exotic_hurled";
            if ((string)comboType.SelectedItem == "Breach-action Shotgun")
                return "shotgun";
            if ((string)comboType.SelectedItem == "Pump Shotgun")
                return "shotgun";
            if ((string)comboType.SelectedItem == "Semi-auto Shotgun")
                return "shotgun";
            if ((string)comboType.SelectedItem == "Automatic Shotgun")
                return "shotgun";
            if ((string)comboType.SelectedItem == "Bolt-action Rifle")
                return "rifle";
            if ((string)comboType.SelectedItem == "Semi-auto Rifle")
                return "rifle";
            if ((string)comboType.SelectedItem == "Assault Rifle")
                return "rifle";
            if ((string)comboType.SelectedItem == "SAW Machine Gun")
                return "rifle";
            if ((string)comboType.SelectedItem == "Light Submachine Gun")
                return "submachinegun";
            if ((string)comboType.SelectedItem == "Heavy Submachine Gun")
                return "submachinegun";
            if ((string)comboType.SelectedItem == "General Machinegun")
                return "tactical";
            if ((string)comboType.SelectedItem == "Heavy Machinegun")
                return "tactical";
            if ((string)comboType.SelectedItem == "Flamethrower")
                return "tactical";
            if ((string)comboType.SelectedItem == "Rocket Launcher")
                return "tactical";
            if ((string)comboType.SelectedItem == "Auto Grenade Launcher")
                return "indirect";
            if ((string)comboType.SelectedItem == "Stand-alone Grenade Launcher")
                return "indirect";
            if ((string)comboType.SelectedItem == "Underbarrel Grenade Launcher")
                return "indirect";
            if ((string)comboType.SelectedItem == "Mortar")
                return "indirect";
            if ((string)comboType.SelectedItem == "Missile Launcher")
                return "guided";
            if ((string)comboType.SelectedItem == "Explosive")
                return "explosives";
            if ((string)comboType.SelectedItem == "Vehicle Weapon")
                return "vehicle";


            return "UNKOWN";
        }
        private string GetTreeNodeName(string name)
        {
            string nodestr = "";
            if (name == "Assault Rifle") nodestr = "arifle";
            else if (name == "Auto Grenade Launcher") nodestr = "autogrenade";
            else if (name == "Automatic Shotgun") nodestr = "ashotgun";
            else if (name == "Backup Pistol") nodestr = "bkuppistol";
            else if (name == "Backup Revolver") nodestr = "bkuprevolver";
            else if (name == "Blunt Melee") nodestr = "bmelee";
            else if (name == "Bolt-action Rifle") nodestr = "brifle";
            else if (name == "Breach-action Shotgun") nodestr = "bashotgun";
            else if (name == "Edged Melee") nodestr = "emelee";
            else if (name == "Exotic Blunt") nodestr = "ebmelee";
            else if (name == "Exotic Edged") nodestr = "eedged";
            else if (name == "Exotic Hurled") nodestr = "ehurled";
            else if (name == "Explosives") nodestr = "explosives";
            else if (name == "Flamethrower") nodestr = "flamethrower";
            else if (name == "General Machinegun") nodestr = "gmachinegun";
            else if (name == "Heavy Machinegun") nodestr = "hmachinegun";
            else if (name == "Heavy Submachine Gun") nodestr = "hsubmachinegun";
            else if (name == "Holdout Pistol") nodestr = "hldpistol";
            else if (name == "Hunting Revolver") nodestr = "huntrevolver";
            else if (name == "Hurled") nodestr = "hurled";
            else if (name == "Light Submachine Gun") nodestr = "lsubmachinegun";
            else if (name == "Missile Launcher") nodestr = "missile";
            else if (name == "Mortar") nodestr = "mortar";
            else if (name == "Pump Shotgun") nodestr = "pshotgun";
            else if (name == "Rocket Launcher") nodestr = "rktlauncher";
            else if (name == "SAW Machine Gun") nodestr = "sawmachinegun";
            else if (name == "Semi-auto Rifle") nodestr = "sarifle";
            else if (name == "Semi-auto Shotgun") nodestr = "sashotgun";
            else if (name == "Service Pistol") nodestr = "svcpistol";
            else if (name == "Service Revolver") nodestr = "svcrevolver";
            else if (name == "Stand-alone Grenade Launcher") nodestr = "sagrenade";
            else if (name == "Underbarrel Grenade Launcher") nodestr = "ugrenade";
            else if (name == "Vehicle Weapon") nodestr = "vehicle";
            else { MessageBox.Show("AddItemToTree: ERROR. Didn't find node"); return null; }
            return nodestr;
        }
        private bool ValidateFields()
        {
            rtTitle.Text.Trim();
            if (rtTitle.Text == "")
            {
                MessageBox.Show("Must give the weapon a name.");
                return false;
            }
            
            if (textCaliber.Text == "")
            {
                MessageBox.Show("Must give the weapon a caliber.");
                return false;
            }
            if (textComplexityDC.Text == "")
            {
                MessageBox.Show("Must give the weapon a complexity.");
                return false;
            }
            if (textDamage.Text == "")
            {
                MessageBox.Show("Must give the weapon a damage rating.");
                return false;
            }
            if (textErrorRange.Text == "")
            {
                MessageBox.Show("Must give the weapon an error range.");
                return false;
            }
            if (textRange.Text == "")
            {
                MessageBox.Show("Must give the weapon a range.");
                return false;
            }
            if (textStreetVal.Text == "")
            {
                MessageBox.Show("Must give the weapon a $treet value.");
                return false;
            }
            if (textThreatRange.Text == "")
            {
                MessageBox.Show("Must give the weapon a threat range.");
                return false;
            }
            if (textWeight.Text == "")
            {
                MessageBox.Show("Must give the weapon a weight.");
                return false;
            }
            if (textWpnSize.Text == "")
            {
                MessageBox.Show("Must give the weapon a size.");
                return false;
            }
            // Letter/#h
            if (textWpnSize.Text.Contains('/') == false)
            {
                MessageBox.Show("Use the format: Letter/#h");
                return false;
            }
            if (textAmmo.Text == "")
            {
                MessageBox.Show(@"Ammo information must be in the form of {number}{letter}{number}.");
                return false;
            }
            else
            {
                const int stateCapacity = 0; const int stateType = 1; const int stateReloads = 2; int stateCurr = stateCapacity; int idx = 0;
                // make sure it's in the correct format (#L#) numberletternumber eg 15M4
                char[] ca = textAmmo.Text.ToCharArray();
                foreach (char z in ca)
                {
                    switch (stateCurr)
                    {
                        case stateCapacity:
                            if (Char.IsNumber(z)) idx++;
                            else if (idx == 0)
                            {
                                MessageBox.Show(@"Ammo information must be in the form of {number}{letter}{number}.");
                                return false;
                            }
                            else { stateCurr = stateType; goto case stateType; }
                                break;
                        case stateType:
                            if (Char.IsLetter(z)) stateCurr = stateReloads;
                            else
                            {
                                MessageBox.Show(@"Ammo information must be in the form of {number}{letter}{number}.");
                                return false;
                            }
                            break;
                        case stateReloads:
                            if (Char.IsNumber(z)) idx++;
                            else
                            {
                                MessageBox.Show(@"Ammo information must be in the form of {number}{letter}{number}.");
                                return false;
                            }

                            break;
                    }
                }


            }
            //if (rtTitle.Text == "")
            //{
            //    MessageBox.Show("Must give the weapon a name.");
            //    return false;
            //}


            return true;
        }
        private bool AddItemToTree(string node, string item)
        {
            MessageBox.Show("AddItemToTree: Adding " + item + " as " + node);
            if (item == null) return false;
            string nodestr = GetTreeNodeName(node);

            MessageBox.Show("AddItemToTree: Matched" + nodestr + " to " + node); 

            TreeNode[] tn = treeWpns.Nodes[0].Nodes.Find(nodestr, true);
        /////    treeWpns.SelectedNode = tn[0];
            TreeNode nod = new TreeNode();
            //MessageBox.Show("AddItemToTree->Node." + 
          
            nod.Name = MakeID(item);
            nod.Text = item;
       ////////    treeWpns.SelectedNode.Nodes.Add(nod);
            tn[0].Nodes.Add(nod);
            MessageBox.Show(String.Format("Added new node {0} for {1} under {2} (nodestr={3})", nod.Name, nod.Text,tn[0].Text, nodestr));
         
            return true;
        }
        private string MakeID(string name)
        {
            string ret = new string(name.ToLower().ToCharArray());
            char[] c = { ' ', ',', '!', '?', '/', '\\' };
            foreach (char z in c)
                ret = ret.Replace(z.ToString(), "");

            XmlLog.Instance.Add("MakeID: Converted " + name + " to " + ret);
            //char c = ' ';
            //ret = ret.Replace(c.ToString(), "");
            return ret;
        }

        /// <summary>
        /// This is called from the WeaponTree when there is:
        /// 1. a selection change on the tree
        /// 2. the node is a leaf node
        /// </summary>
        /// <param name="id"></param>
        public void UpdateFormFromTree(string id)
        {
#if DEBUG
            XmlLog.Instance.Add("UpdateFormFromTree: Starting");
            XmlLog.Instance.Add("UpdateFormFromTree: Looking for node " + id);
#endif            

            // query xml file to get the weapon
            IEnumerable<XElement> singleWeapon = WeaponDB.Instance.FindWeaponByNode(id);

            foreach (XElement xe in singleWeapon)
            {
                MessageBox.Show("Iterating through singleWeapon elements (" + xe + ")");
                if (xe.Name == "WEAPON" && (string)xe.Element("NAME").Attribute("id") == id)
                {
                    //MessageBox.Show("Apparently " + id + " matches " + (string)xe.Element("NAME"));
                    //MessageBox.Show(String.Format("xe.Element(NAME).Attribute(id) = {0})", xe.Element("NAME").Attribute("id").Value));
                    rtTitle.Text = (string)xe.Element("NAME");
                    textCaliber.Text = xe.Element("CALIBER").Value;
                    numAddOns.Value = (int)xe.Element("ADDONS");
                    numGearCaliber.Value = (int)xe.Element("PICK");
                    numRecoil.Value = (int)xe.Element("RECOIL");
                    textComplexityDC.Text = (string)xe.Element("COMPLEXITY").Element("DC");
                    textComplexityMod.Text = (string)xe.Element("COMPLEXITY").Element("MOD");
                    textDamage.Text = (string)xe.Element("DMG");
                    textErrorRange.Text = (string)xe.Element("ERROR");
                    textThreatRange.Text = (string)xe.Element("THREAT");
                    textWeight.Text = (string)xe.Element("WEIGHT");
                    textWpnQual.Text = (string)xe.Element("QUALITY");
                    textWpnSize.Text = (string)xe.Element("SIZE") + "/" + (string)xe.Element("HANDS");
                    textYear.Text = (string)xe.Element("YEAR");
                    textRange.Text = (string)xe.Element("RANGE");
                    textStreetVal.Text = (string)xe.Element("STREET");
                    // comboType
                    comboType.SelectedItem = (string)xe.Element("TYPE");

                    // ammo labels TODO
                    char[] cMagCapacity = new char[5];
                    char[] cNumMags = new char[5];
                    char cMagType = 'Z';
                    textAmmo.Text = (string)xe.Element("AMMO");
                    char[] ca = textAmmo.Text.ToCharArray();
                    const int stateCapacity = 0; const int stateType = 1; const int stateReloads = 2; int stateCurr = stateCapacity; int idx = 0;
                    foreach (char z in ca)
                    {
                        switch (stateCurr)
                        {
                            case stateCapacity:
                                if (Char.IsNumber(z)) { cMagCapacity[idx++] = z;  }

                                else { stateCurr = stateType; goto case stateType;  }
                                break;
                            case stateType:
                                if (Char.IsLetter(z))
                                {
                                    stateCurr = stateReloads;
                                    cMagType = z;
                                    idx = 0;
                                    
                                }
                                break;
                            case stateReloads:
                                if (Char.IsNumber(z)) cNumMags[idx++] = z;

                                break;
                        }
                    }
                    // set the labels
                    string str = new String(cMagCapacity);
                    string str2 = new String(cNumMags);
                    labelNumMags.Text = (str2 += " fully loaded");
                    labelRoundsType.Text = str + "-round " + Weapon.MagType(cMagType);
                   

                    // range max TODO


                    // picWeapon TODO
                    break;
                }
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            MessageBox.Show(String.Format("Deleting {0}", treeWpns.SelectedNode.Name));
            // remove from xml file
            XElement xdoc = XElement.Load(@"Data Files\Weapons.txt");
            var singleWeapon = from w in xdoc.Elements("WEAPONS").Elements("WEAPON")
                               where w.Element("NAME").Attribute("id").Value == treeWpns.SelectedNode.Name
                               select w;

            foreach (var d in singleWeapon)
            {
                d.Remove();
            }
            xdoc.Save(@"Data Files\Weapons.txt");

            // remove from tree
            TreeNode delme = treeWpns.SelectedNode;
            treeWpns.Nodes.Remove(delme);
        }

    }

    public class WeaponTree : System.Windows.Forms.TreeView
    {
        public WeaponTree() { }

        

        protected override void OnAfterSelect(TreeViewEventArgs ev)
        {
            base.OnAfterSelect(ev);

            if (ev.Node.FirstNode == null)  // if we're a leaf node...
            {
                MessageBox.Show(String.Format("WeaponTree.UpdateFormFromTree(id={0})", ev.Node.Name));
                 //                                  Example:     beretta92
                ((WeaponInventoryForm)Parent).UpdateFormFromTree(ev.Node.Name);
            }
        }

    }

}
